package com.nageoffer.onecoupon.merchant.admin.service.basics.chain;

import com.nageoffer.onecoupon.merchant.admin.service.handler.filter.CouponTemplateCreateParamBaseVerifyChainFilter;
import com.nageoffer.onecoupon.merchant.admin.service.handler.filter.CouponTemplateCreateParamNotNullChainFilter;
import com.nageoffer.onecoupon.merchant.admin.service.handler.filter.CouponTemplateCreateParamVerifyChainFilter;
import org.springframework.beans.BeansException;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * 功能
 * 作者 伟大哥
 * 日期 2025/3/29,10:15
 **/

@Component
public class MerchantAdminChainContext<T> implements ApplicationContextAware, CommandLineRunner {


    /**
     * 应用上下文，我们这里通过 Spring IOC 获取 Bean 实例
     */
    private ApplicationContext applicationContext;


    /**
     * 保存商家后管责任链实现类
     * <p>
     * Key：{@link MerchantAdminAbstractChainHandler#mark()}
     * Val：{@link MerchantAdminAbstractChainHandler} 一组责任链实现 Spring Bean 集合
     * <p>
     * 比如有一个优惠券模板创建责任链，实例如下：
     * Key：MERCHANT_ADMIN_CREATE_COUPON_TEMPLATE_KEY
     * Val：
     * - 验证优惠券信息基本参数是否必填 —— 执行器 {@link CouponTemplateCreateParamNotNullChainFilter}
     * - 验证优惠券信息基本参数是否按照格式传递 —— 执行器 {@link CouponTemplateCreateParamBaseVerifyChainFilter}
     * - 验证优惠券信息基本参数是否正确，比如商品数据是否存在等 —— 执行器 {@link CouponTemplateCreateParamVerifyChainFilter}
     * - ......
     */
    private final Map<String, List<MerchantAdminAbstractChainHandler>> abstractChainHandlerContainer = new HashMap<>();

    /**
     * 责任链组件执行
     *
     * @param mark         责任链组件标识
     * @param requestParam 请求参数
     */
    public void handler(String mark, T requestParam) {
        // 根据 mark 标识从责任链容器中获取一组责任链实现 Bean 集合
        List<MerchantAdminAbstractChainHandler> abstractChainHandlers = abstractChainHandlerContainer.get(mark);
        if (CollectionUtils.isEmpty(abstractChainHandlers)) {
            throw new RuntimeException(String.format("[%s] Chain of Responsibility ID is undefined.", mark));
        }
        abstractChainHandlers.forEach(each -> each.handler(requestParam));
    }
    /**
     * 重写 run 方法，用于初始化并排序责任链处理器。
     *
     * 该方法从 Spring 应用上下文中获取所有类型为 MerchantAdminAbstractChainHandler 的 Bean，
     * 并根据其标记（mark）将这些 Bean 分组存储到 abstractChainHandlerContainer 中。
     * 最后，对每个标记对应的责任链处理器集合进行排序，确保优先级小的处理器排在前面。
     *
     * @param args 命令行参数，未在此方法中使用
     * @throws Exception 如果执行过程中发生异常
     */
    @Override
    public void run(String... args) throws Exception {
        // 从应用上下文中获取所有 MerchantAdminAbstractChainHandler 类型的 Bean
        Map<String, MerchantAdminAbstractChainHandler> chainFilterMap = applicationContext.getBeansOfType(MerchantAdminAbstractChainHandler.class);

        // 遍历所有获取到的 Bean，根据其 mark 分组存储到 abstractChainHandlerContainer 中
        chainFilterMap.forEach((beanName, bean) -> {
            // 判断当前 mark 是否已经存在于容器中，若存在则直接添加到对应集合，否则创建新的集合
            List<MerchantAdminAbstractChainHandler> abstractChainHandlers = abstractChainHandlerContainer.getOrDefault(bean.mark(), new ArrayList<>());
            abstractChainHandlers.add(bean);
            abstractChainHandlerContainer.put(bean.mark(), abstractChainHandlers);
        });

        // 对每个 mark 对应的责任链处理器集合进行排序，确保优先级小的处理器排在前面
        abstractChainHandlerContainer.forEach((mark, unsortedChainHandlers) -> {
            unsortedChainHandlers.sort(Comparator.comparing(Ordered::getOrder));
        });
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
